﻿using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Script.Serialization;
using Kiiro.Common.Entities;
using Kiiro.Common.Interfaces;
using Kiiro.Common.Utility;
using Kiiro.ExceptionManagement;
using Kiiro.Logging;
using Microsoft.SharePoint.Utilities;

namespace Kiiro.Model
{
    /// <summary>
    /// 
    /// </summary>
    public class AjaxModel
    {
        #region Singleton

        private static AjaxModel instance = null;
        private static readonly object threadLock = new object ( );

        private AjaxModel ( )
        {
        }

        public static AjaxModel Instance
        {
            get
            {
                lock ( threadLock )
                {
                    if ( instance == null )
                    {
                        instance = new AjaxModel ( );
                    }
                }
                return instance;
            }
        }

        #endregion

        public bool HandleAjaxRequest (
            HttpRequest request,
            HttpResponse response,
            IPermissions iPermissions,
            Guid siteCollectionId,
            string serverRelativeUrl,
            User currentUser )
        {
            bool success = false;

            try
            {
                string strType = request.Params [ Constants.AJAXQueryString.OperationType ];

                if ( !string.IsNullOrEmpty ( strType ) )
                {
                    AjaxOperationType type = ( AjaxOperationType ) Enum.Parse ( typeof ( AjaxOperationType ), strType, true );

                    switch ( type )
                    {
                        case AjaxOperationType.SaveWork:
                            success = Save ( request, response, iPermissions, siteCollectionId, serverRelativeUrl, currentUser );
                            break;
                        case AjaxOperationType.SaveUserStatus:
                            success = SaveUserStatus ( request, response, iPermissions, siteCollectionId, serverRelativeUrl, currentUser );
                            break;
                        case AjaxOperationType.SaveProjectSummaryNote:
                            success = SaveProjectSummaryNote ( request, response, iPermissions, siteCollectionId, serverRelativeUrl, currentUser );
                            break;
                        case AjaxOperationType.LookupADUserInformation:
                            success = LookupADUserInformation ( request, response );
                            break;
                        case AjaxOperationType.MoveFileOrFolder:
                            success = MoveFileOrFolder ( request, response, siteCollectionId, serverRelativeUrl );
                            break;
                        case AjaxOperationType.RenameFileOrFolder:
                            success = RenameFileOrFolder ( request, response, siteCollectionId, serverRelativeUrl, currentUser );
                            break;
                        default:
                            throw new Exception ( "Unrecognized operation type." );
                    }
                }
            }
            catch ( Exception ex )
            {
                success = false;
                ExceptionManager.HandleException ( ex, true );
            }

            return success;
        }

        /// <summary>
        /// Save the project data supplied in the request params
        /// </summary>
        private bool SaveProjectSummaryNote (
            HttpRequest request,
            HttpResponse response,
            IPermissions iPermissions,
            Guid siteCollectionId,
            string serverRelativeUrl,
            User currentUser )
        {
            string temp;
            bool success = false; ;
            Project project = null;
            int itemId = default ( int );

            try
            {
                int.TryParse ( request.Params [ Constants.AJAXQueryString.ItemId ], out itemId );

                if ( itemId != default ( int ) )
                {
                    project = ProjectsModel.GetProjectById ( itemId, siteCollectionId, serverRelativeUrl );

                    // PERMISSIONS ARE CHECKED IN THE PROJECT MODEL

                    if ( project != null )
                    {
                        project.ModifiedBy = currentUser;
                        project.ModifiedDate = DateTime.Now;

                        temp = request.Params [ Constants.AJAXQueryString.StatusNote ];
                        if ( temp != null )
                            project.SummaryNote = temp.Replace ( "\n", " " );

                        temp = request.Params [ Constants.AJAXQueryString.AjaxCurrentUser ];
                        project.LastUpdatedSummaryNote = string.IsNullOrEmpty ( temp ) ? "Unknown" : temp;

                        ProjectsModel.UpdateSummaryNote ( project, siteCollectionId, serverRelativeUrl );
                    }
                }
            }
            catch ( Exception ex )
            {
                ExceptionManager.HandleException ( ex, true );
            }

            SerializeToResponse ( response, project );
            return success;
        }

        /// <summary>
        ///  Save the user status supplied in the request params
        /// </summary>
        private bool SaveUserStatus (
            HttpRequest request,
            HttpResponse response,
            IPermissions iPermissions,
            Guid siteCollectionId,
            string serverRelativeUrl,
            User currentUser )
        {
            string temp;
            bool success = false;
            User user = new User ( );
            int itemId = default ( int );

            try
            {
                int.TryParse ( request.Params [ Constants.AJAXQueryString.ItemId ], out itemId );

                if ( itemId != default ( int ) )
                {
                    user = UserModel.GetUserById ( itemId, siteCollectionId, serverRelativeUrl );

                    // PERMISSIONS ARE CHECKED IN THE USER MODEL

                    if ( user != null )
                    {
                        string beforeStatusNote = user.StatusNote;

                        user.ModifiedBy = currentUser;
                        user.ModifiedDate = DateTime.Now;

                        temp = request.Params [ Constants.AJAXQueryString.StatusNote ];
                        if ( temp != null )
                            user.StatusNote = temp.Replace ( "\n", " " );

                        UserModel.Save ( user, siteCollectionId, serverRelativeUrl );
                    }
                }
            }
            catch ( Exception ex )
            {
                ExceptionManager.HandleException ( ex, false );
            }

            SerializeToResponse ( response, user );
            return success;
        }

        /// <summary>
        /// Moves a file or folder entity
        /// </summary>
        private bool MoveFileOrFolder (
            HttpRequest request,
            HttpResponse response,
            Guid siteCollectionId,
            string serverRelativeUrl )
        {
            bool success = false;
            int itemId = default ( int );
            Document document = new Document ( );

            try
            {
                int.TryParse ( request.Params [ Constants.AJAXQueryString.ItemId ], out itemId );
                string destination = request.Params [ Constants.AJAXQueryString.Destination ];

                if ( itemId != default ( int ) )
                {
                    document = DocumentModel.MoveDocument ( itemId, destination, siteCollectionId, serverRelativeUrl );
                }
            }
            catch ( Exception ex )
            {
                ExceptionManager.HandleException ( ex, false );
            }

            SerializeToResponse ( response, document );
            return success;
        }

        /// <summary>
        /// Rename a file or folder entity
        /// </summary>
        private bool RenameFileOrFolder (
            HttpRequest request,
            HttpResponse response,
            Guid siteCollectionId,
            string serverRelativeUrl,
            User currentUser )
        {
            bool success = false;
            int itemId = default ( int );
            Document document = new Document ( );

            try
            {
                int.TryParse ( request.Params [ Constants.AJAXQueryString.ItemId ], out itemId );
                string destination = request.Params [ Constants.AJAXQueryString.Destination ];
                string name = request.Params [ Constants.AJAXQueryString.Name ];

                if ( itemId != default ( int ) )
                {
                    document = DocumentModel.GetDocumentById ( itemId, siteCollectionId, serverRelativeUrl );

                    if ( document != null )
                    {
                        document.EditType = EditType.Updated;
                        document.SiteCollectionId = siteCollectionId;

                        bool updateDoc = false;

                        if ( document.IsFolder )
                        {
                            if ( document.Title != name )
                            {
                                document.FolderUrl = document.ServerRelativeUrl.Remove ( document.ServerRelativeUrl.LastIndexOf ( "/" ) );
                                document.Title = name;
                                updateDoc = true;
                            }
                        }
                        else
                        {
                            string title = document.Title;
                            string newName = title.Replace ( title.Substring ( 0, title.LastIndexOf ( "." ) ), name );
                            if ( document.Title != newName )
                            {
                                document.Url = document.Url.Remove ( document.Url.LastIndexOf ( "/" ) + 1 );
                                document.Title = newName;
                                updateDoc = true;
                            }
                        }

                        if ( updateDoc )
                        {
                            document = DocumentModel.Save ( document, null, currentUser, siteCollectionId, serverRelativeUrl );
                        }
                    }
                }
            }
            catch ( Exception ex )
            {
                ExceptionManager.HandleException ( ex, false );
            }

            SerializeToResponse ( response, document );
            return success;
        }

        /// <summary>
        /// Save the Work data supplied in the request params
        /// </summary>
        private bool Save (
            HttpRequest request,
            HttpResponse response,
            IPermissions iPermissions,
            Guid siteCollectionId,
            string serverRelativeUrl,
            User currentUser )
        {
            bool success = false;
            Work work = new Work ( );
            int itemId = default ( int );
            string temp = string.Empty;
            string projectSRU = string.Empty;

            bool isPortal = SPHelpers.IsPortal ( siteCollectionId, serverRelativeUrl );

            try
            {
                int.TryParse ( request.Params [ Constants.AJAXQueryString.ItemId ], out itemId );
                
                if ( itemId != default ( int ) )
                {
                    if ( isPortal )
                    {
                        temp = request.Params [ Constants.AJAXQueryString.ProjectSRU ];
                        if ( !string.IsNullOrEmpty ( temp ) && temp != null )
                        {
                            projectSRU = temp;
                            if ( projectSRU.EndsWith ( "/" ) ) projectSRU.TrimEnd ( '/' );
                            work = WorkModel.GetById ( itemId, siteCollectionId, projectSRU );
                        }
                    }
                    else
                        work = WorkModel.GetById ( itemId, siteCollectionId, serverRelativeUrl );

                    if ( work != null )
                    {
                        // PERMISSIONS ARE CHECKED IN THE WORK MODEL

                        work.ModifiedBy = currentUser;
                        work.ModifiedDate = DateTime.Now;
                        work.BeforeAssignedWork = work.AssignedWork;
                        work.BeforePercentComplete = work.PercentageComplete;
                        work.BeforeStart = work.StartDate;
                        work.BeforeEnd = work.EndDate;
                        work.BeforeStatus = work.Status;

                        temp = request.Params [ Constants.AJAXQueryString.StatusNote ];
                        if ( temp != null )
                            work.StatusNote = temp.Replace ( "\n", " " );

                        temp = request.Params [ Constants.AJAXQueryString.PercentComplete ];
                        if ( work.WorkItemType == WorkType.Task && !string.IsNullOrEmpty ( temp ) )
                            work.PercentageComplete = float.Parse ( temp );

                        temp = request.Params [ Constants.AJAXQueryString.IssueStatus ];
                        if ( work.WorkItemType == WorkType.Issue && !string.IsNullOrEmpty ( temp ) )
                            work.Status = ( StatusType ) int.Parse ( temp );

                        if ( isPortal )
                            WorkModel.Save ( work, siteCollectionId, projectSRU, true );
                        else
                            WorkModel.Save ( work, siteCollectionId, serverRelativeUrl, true );
                    }
                }
            }
            catch ( Exception ex )
            {
                ExceptionManager.HandleException ( ex, false );
            }

            SerializeToResponse ( response, work );
            return success;
        }

        private bool LookupADUserInformation ( HttpRequest request, HttpResponse response )
        {
            bool success = true;
            string userLogin = null;
            string url = request.Url.ToString ( ).ToLower ( );
            User user = null;

            try
            {
                userLogin = request.Params [ Constants.AJAXQueryString.UserLogin ];

                if ( !string.IsNullOrEmpty ( userLogin ) )
                {
                    user = UserModel.GetADUser ( userLogin );

                    success = ( url.Contains ( Constants.PortalFileUrls.UserNew.ToLower ( ) ) && !string.IsNullOrEmpty ( user.Login ) && !user.IsADGroup ) ||
                        ( url.Contains ( Constants.PortalFileUrls.GroupNew.ToLower ( ) ) && !string.IsNullOrEmpty ( user.Login ) && user.IsADGroup );
                }
            }
            catch ( Exception ex )
            {
                ExceptionManager.HandleException ( ex, false );
            }

            SerializeToResponse ( response, success ? user : new User ( ) );
            return success;
        }

        private void SerializeToResponse ( HttpResponse response, BaseEntity entity )
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer ( );
            string data = serializer.Serialize ( entity );
            char [ ] chars = data.PadRight ( data.Length + 100, ' ' ).ToCharArray ( );

            response.Write ( chars, 0, chars.Length - 1 );
            response.Flush ( );
            response.Close ( );
        }
    }
}

/*************************************************************************
 * 
 * $Log: /Internal Projects/Kiiro/Kiiro.Model/AjaxModel.cs $
 * 
 * 25    2/08/10 5:04p Camerons
 * 
 * 24    1/25/10 1:17p Camerons
 * 
 * 23    1/21/10 2:40p Camerons
 * 
 * 22    1/12/10 12:03p Camerons
 * 
 * 21    12/02/09 2:50p Camerons
 * 
 * 20    26/11/09 10:35a Camerons
 * 
 * 19    23/11/09 3:47p Camerons
 * 
 * 18    17/11/09 6:46p Camerons
 * 
 * 17    10/26/09 9:15a Adamw
 * fix for ' in submitted values
 * 
 * 16    9/10/09 4:25p Camerons
 * Repaired some code for AD Lookup
 * 
 * 15    10/09/09 3:23p Stefanf
 * 
 * 14    10/09/09 2:51p Stefanf
 * 
 * 13    8/10/09 6:41p Camerons
 * Updates for Server License
 * 
 * 12    1/10/09 3:28p Camerons
 * Load Expanded ADGroups into drop down on NewTeamMember. Create user on
 * demand if selected user doesn't exist.
 * 
 * 11    21/09/09 3:30p Camerons
 * First batch of changes for 1.1.x.x - Security groups update
 * 
 * 10    11/09/09 4:05p Shafia
 * 
 * 9     9/04/09 10:27a Stefanf
 * 
 * 8     31/08/09 12:15p Shafia
 * assign the last updated property for status note to current user
 * 
 * 7     17/08/09 10:29a Camerons
 * Added check-in comments section
 * 
 ************************************************************************/